﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Globalization;
using System.Web.Mvc;

namespace Mvc.XForms.Utilities {
	public class CultureAwareModelValidator<T> : ModelValidator<T> {
		private string cultureFormat = "<span class=\"errMessage {0}\">{1}</span>";
		protected CultureInfo CurrentCulture { get; set; }

		public virtual string CultureFormat {
			get { return cultureFormat; }
			set { cultureFormat = value; }
		}

		public CultureAwareModelValidator(T objToValidate, ModelStateDictionary modelState)
			: this(objToValidate, modelState, string.Empty) { }

		public CultureAwareModelValidator(T objToValidate, ModelStateDictionary modelState, string prefix)
			: base(objToValidate, modelState, prefix) { }

		public void Rule(Expression<Func<T, object>> bind, bool rule, string errorMessage, CultureInfo culture) {
			CurrentCulture = culture;
			Rule(bind, rule, errorMessage);
			CurrentCulture = null;
		}

		public void String(Expression<Func<T, object>> bind, Func<string, bool> rule, string errorMessage, CultureInfo culture) {
			CurrentCulture = culture;
			String(bind, rule, errorMessage);
			CurrentCulture = null;
		}

		public virtual void RequiredString(Expression<Func<T, object>> bind, string errorMessage, CultureInfo culture) {
			String(bind, str => str.Length == 0, errorMessage, culture);
		}

		public void Error(Expression<Func<T, object>> bind, string errorMessage, CultureInfo culture) {
			CurrentCulture = culture; 
			Error(bind, errorMessage);
			CurrentCulture = null;
		}

		public void Error(string key, string errorMessage, CultureInfo culture) {
			if (culture != null)
				errorMessage = string.Format("<span class=\"errMessage {0}\">{1}</span>", culture.Name, errorMessage);

			ModelState.AddModelError(key, errorMessage);
		}

		public override void Error(string key, string errorMessage) {
			if (CurrentCulture != null)
				errorMessage = string.Format(cultureFormat, CurrentCulture.Name, errorMessage);

			base.Error(key, errorMessage);
		}

		public void CultureAwareEnumerable<TNew>(Expression<Func<T, IEnumerable<TNew>>> bind, Action<TNew, CultureAwareModelValidator<TNew>> validationAction) {
			var listToValidate = bind.Compile()(ObjectToValidate);

			var bindStr = bind.Body.ExtractID();
			var prefix = string.IsNullOrEmpty(Prefix) ? bindStr : string.Concat(Prefix, ExpressionHelper.Separator, bindStr);

			listToValidate.ForEach((obj, i) => {
				var indexedPrefix = string.Concat(prefix, ExpressionHelper.IndexSeparator, i);
				var validator = new CultureAwareModelValidator<TNew>(obj, ModelState, indexedPrefix);
				validationAction(obj, validator);
			});
		}
	}
}
